﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text.RegularExpressions;
using ClumsyWordsWP8.Resources;
using System.Threading.Tasks;
using System.Net.Http;
using System.Xml.Linq;
using System.Linq;
using System.Globalization;
using Newtonsoft.Json;
using ClumsyWordsWP8.DataSerializer;

namespace ClumsyWordsWP8.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {

        private const string _stands4uri = "http://www.stands4.com/services/v2/defs.php?uid=3021&tokenid=vE8RzRNRjAHQIJuR&word=";

        public MainViewModel()
        {
            this.RecentItems = new ObservableCollection<WordDefinitionViewModel>();
            this.FavouriteItems = new ObservableCollection<WordDefinitionViewModel>();
            this.SearchResult = new WordDefinitionViewModel();
            this.IsAddToRecentEnabled = true;
        }

        /// <summary>
        /// A collection for items that have been recently looked up.
        /// </summary>
        public ObservableCollection<WordDefinitionViewModel> RecentItems { get; private set; }

        /// <summary>
        /// A collection for items that have been added to favourites list
        /// </summary>
        public ObservableCollection<WordDefinitionViewModel> FavouriteItems { get; private set; }

        /// <summary>
        /// The result of the last quick search.
        /// </summary>
        private WordDefinitionViewModel _searchResult;
        public WordDefinitionViewModel SearchResult 
        {
            get { return this._searchResult; }
            
            set 
            {
                this._searchResult = value;
                NotifyPropertyChanged("SearchResult"); 
            }
        }

        /// <summary>
        /// The current term that is being searched for.
        /// </summary>
        private string _searchTerm;
        public string SearchTerm
        {
            get { return this._searchTerm; }

            set
            {
                this._searchTerm = value;
                NotifyPropertyChanged("SearchTerm");
            }
        }

        /// <summary>
        /// Shows if a SearchResult should be added to the RecentItems
        /// </summary>
        private bool _isAddToRecentEnabled;
        public bool IsAddToRecentEnabled 
        {
            get { return this._isAddToRecentEnabled; }
            
            set 
            {
                this._isAddToRecentEnabled = value;
                NotifyPropertyChanged("IsAddToRecentEnabled"); 
            }
        }

        /// <summary>
        /// Sends a request to the STANDS4 API and presents the result as a SearchResult
        /// </summary>
        /// <param name="word">The word that is being searched for</param>
        /// <returns></returns>
        public async Task<WordDefinitionViewModel> CheckWordAsync(string word)
        {
            PartOfSpeechConverter converter = new PartOfSpeechConverter();
            string wordUri = _stands4uri + word;

            HttpClient client = new HttpClient();

            HttpResponseMessage response = await client.GetAsync(wordUri);
            string responseText = await response.Content.ReadAsStringAsync();
            //TODO : Check if there is a responseText before parsing it.

            XDocument doc = XDocument.Parse(responseText);
            if (doc.Element("results").Elements("results") != null)
            {
                //Composing the search result from xml
                WordDefinitionViewModel result = new WordDefinitionViewModel()
                {
                    Term = doc.Element("results").Elements("result").First().Element("term").Value.ToString(),
                    TermPropertiesList
                    = (from _props in doc.Element("results").Elements("result")
                       select new TermProperties
                       {
                           Definition = _props.Element("definition").Value.ToString(),
                           Example = _props.Element("example").Value.ToString(),
                           PartOfSpeech = (PartOfSpeech)converter.ConvertBack(_props.Element("partofspeech").Value.ToString(), typeof(string), null, CultureInfo.CurrentCulture)
                       }).GroupBy(x => x.PartOfSpeech)
                         .Select(g => new Group<TermProperties, PartOfSpeech>(g.Key, g)).ToList()
                };

                return result;
            }
            return default(WordDefinitionViewModel);

            //TODO : Check if sth has failed.
        }
       
        public bool IsDataLoaded
        {
            get;
            private set;
        }

        /// <summary>
        /// Loads the RecentItems and FavouriteItems from isolated storage
        /// </summary>
        public void LoadData()
        {
            var recent = JsonConvert.DeserializeObject<ObservableCollection<WordDefinitionViewModel>>(CustomDataSerializer<ObservableCollection<WordDefinitionViewModel>>.ReadData("recent.store"));
            if (recent != null) this.RecentItems = recent;

            var favourites = JsonConvert.DeserializeObject<ObservableCollection<WordDefinitionViewModel>>(CustomDataSerializer<ObservableCollection<WordDefinitionViewModel>>.ReadData("favourites.store"));
            if (favourites != null) this.FavouriteItems = favourites;

            this.IsDataLoaded = true;
        }

        #region NotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}